package web

import (
	"context"
	"mime"
	"net/http"
	_ "net/http/pprof"
	"path/filepath"
	"strconv"

	"gddgame.cc/galaxy/utils/def"
	"gddgame.cc/galaxy/utils/uuid"
	"github.com/go-chi/chi"
)

type httpServer struct {
	engine *engine
	router *router
	Server *http.Server
}

func newServer(engine *engine, address string, router *router) *httpServer {
	server := &httpServer{engine, router, nil}
	server.Server = &http.Server{Addr: address, Handler: router.root}

	// 生成context
	router.root.Use(func(handler http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			server.contextMiddleware(func(writer http.ResponseWriter, request *http.Request) {
				handler.ServeHTTP(writer, request)
			}, w, r)
		})
	})

	if engine.debug {
		router.debug()
	}
	router.init()

	return server
}

func (s *httpServer) Listen() error {
	go func() {
		s.engine.logger.Debugf("[ Web ] listen web：%#v", s.Server.Addr)
		err := s.Server.ListenAndServe()
		if err != nil && err != http.ErrServerClosed {
			s.engine.logger.Error(err)
		}
	}()
	return nil
}

func (s *httpServer) Close() error {
	return s.Server.Close()
}

func (s *httpServer) GetRouter() Router {
	return s.router
}

func (s *httpServer) contextMiddleware(next http.HandlerFunc, writer http.ResponseWriter, request *http.Request) {
	ctx := request.Context()
	rctx := s.engine.pool.Get().(*contextInline)
	rctx.Reset()
	rctx.request = request
	rctx.context = chi.RouteContext(ctx)
	rctx.responseWrite = writer
	rctx.Logger = s.engine.logger

	request = request.WithContext(context.WithValue(ctx, RouteCtxKey, rctx))
	next(writer, request)
	s.engine.pool.Put(rctx)
}

func Redirect(context def.Context, url string, code int) {
	switch c := context.(type) {
	case *contextInline:
		http.Redirect(c.responseWrite, c.request, url, code)
	default:
	}
}

func Download(context def.Context, content []byte, filename string, t string) error {
	switch c := context.(type) {
	case *contextInline:
		writer := c.Writer()
		c.isClose = true
		if filename == "" {
			filename = uuid.RandomString()
		} else if t == "" {
			t = mime.TypeByExtension(filepath.Ext(filename))
		}
		writer.Header().Set("Content-Disposition", "attachment; filename="+filename)
		if t == "" {
			t = http.DetectContentType(content)
		}
		//v, _ := strconv.ParseInt(strconv.FormatInt(int64(len(content)), 10), 10, 64)
		//fmt.Println(len(content), strconv.FormatInt(int64(len(content)), 10), v)
		writer.Header().Set("Content-Type", t)
		writer.Header().Set("Content-Length", strconv.FormatInt(int64(len(content)), 10))
		writer.WriteHeader(http.StatusOK)
		_, err := writer.Write(content)

		return err
	default:
	}
	return nil
}
